/*
** exec.c for exec in /home/vriely/Work/Unix/Myftp_rendu/serv-src
**
** Made by Samuel Vrielynck
** Login   <vriely_s@epitech.net>
**
** Started on  Thu Apr 05 12:48:53 2012 Samuel Vrielynck
** Last update Thu Jul 19 17:34:04 2012 pierrick druart
*/

#include		<netdb.h>
#include		<sys/socket.h>
#include		<stdio.h>
#include		<stdlib.h>
#include		<string.h>

#include		"server.h"

static void		set(t_fd *fds, int servfd, t_list *clients)
{
  struct s_client	*client;
  struct s_item		*cur;

  cur = clients->head;
  FD_ZERO(&(fds->rfds));
  FD_ZERO(&(fds->wfds));
  FD_SET(STDIN_FILENO, &(fds->rfds));
  FD_SET(servfd, &(fds->rfds));
  while (cur != NULL)
    {
      client = (struct s_client *) cur->content;
      if (client->send->size > 0)
	FD_SET(client->sock, &(fds->wfds));
      FD_SET(client->sock, &(fds->rfds));
      cur = cur->next;
    }
}

static int		do_select(t_fd *fds, t_list *clients, t_game *game)
{
  struct timeval	tv;
  int			ret;

  set(fds, game->serverfd, clients);
  printf("sleepingtime:%ld\n", game->sleep);
  if (clients->len == 0 || game->sleep == 0)
    ret = select(game->maxfd + 1, &(fds->rfds), &(fds->wfds), NULL, NULL);
  else
    {
      tv.tv_sec = 0;
      tv.tv_usec = game->sleep;
      ret = select(game->maxfd + 1, &(fds->rfds), &(fds->wfds), NULL, &tv);
    }
  if (ret == -1)
    perror("select()");
  return (ret);
}

static void		add_new_client(t_list *clients, int fdserver)
{
  struct s_client	*client;
  struct sockaddr_in	sin;
  int			sin_size;

  sin_size = sizeof(struct sockaddr_in);
  client = (struct s_client *)malloc(sizeof(struct s_client));
  if (client != NULL)
    {
      client->sock = accept(fdserver, (struct sockaddr *) &sin,
			    (socklen_t *) &sin_size);
      if (client->sock == -1)
	{
	  perror("accept()");
	  free(client);
	}
      else
	{
	  client->gamer = NULL;
	  client->send = new_string("BIENVENUE\n");
	  clients->add_back(clients, client);
	  client->rcv = new_string("");
	  printf("New Client : %d\n", client->sock);
	}
    }
}

static void		exec_else(t_list *clients, t_game *game,
    long unsigned int elapsed_time, t_fd *fds)
{
  check_event(clients, game, elapsed_time);
  drop_obj(game, elapsed_time);
  check_client(clients, fds, game, elapsed_time);
}

void			exec(t_game *game)
{
  t_list		*clients;
  struct timeval	beg;
  t_fd			fds;
  long unsigned int	elapsed_time;

  clients = new_list();
  game->maxfd = game->serverfd;
  while (1)
  {
    gettimeofday(&beg, NULL);
    if (do_select(&fds, clients, game) == -1)
      break;
    if (FD_ISSET(STDIN_FILENO, &(fds.rfds)))
      break;
    else if (FD_ISSET(game->serverfd, &(fds.rfds)))
      add_new_client(clients, game->serverfd);
    if ((elapsed_time = init_before_exe(game, &beg)) == 0)
      continue;
    exec_else(clients, game, elapsed_time, &fds);
    if (check_winner_egg(game->team, elapsed_time))
      break;
    check_event_mnt(clients, game);
  }
  clients->clear(clients, &erase_client);
  free(clients);
}
